package pl.droidsonroids.gif;

import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ColorSpace;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import ohos.utils.net.Uri;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

/**
 * GifViewUtils
 */
final class GifViewUtils {
    /**
     * default density
     */
    public static final int DENSITY_DEFAULT = 0;
    /**
     * density none
     */
    public static final int DENSITY_NONE = 65535;
    static final List<String> SUPPORTED_RESOURCE_TYPE_NAMES = Arrays.asList("raw", "drawable", "mipmap");

    private GifViewUtils() {
    }

    static GifImageViewAttributes initImageView(Image view, AttrSet attrs, int defStyleAttr, int defStyleRes)
            throws NotExistException, WrongTypeException, IOException {
        if (attrs != null) {
            final GifImageViewAttributes viewAttributes = new GifImageViewAttributes(view, attrs, defStyleAttr,
                    defStyleRes);
            final int loopCount = viewAttributes.mLoopCount;
            if (loopCount >= 0) {
                applyLoopCount(loopCount, view.getForegroundElement());
                applyLoopCount(loopCount, view.getBackgroundElement());
            }
            return viewAttributes;
        }
        return new GifImageViewAttributes();
    }

    static void applyLoopCount(final int loopCount, final Element drawable) {
        if (drawable instanceof GifDrawable) {
            ((GifDrawable) drawable).setLoopCount(loopCount);
        }
    }

    static boolean setResource(Image view, boolean isSrc, int resId) throws IOException {
        ResourceManager res = view.getResourceManager();
        if (res != null) {
            try {
                GifDrawable drawable = new GifDrawable(view.getContext(), res, resId);
                if (isSrc) {
                    view.setForeground(drawable);
                } else {
                    view.setBackground(drawable);
                }
                return true;
            } catch (IOException e) {
                // ignored
            } catch (NotExistException e) {
                e.printStackTrace();
            } catch (WrongTypeException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    static boolean setGifImageUri(Image imageView, Uri uri) {
        if (uri != null) {
            try {
                imageView.setForeground(new GifDrawable(DataAbilityHelper.creator(imageView.getContext()), uri));
                return true;
            } catch (IOException | DataAbilityRemoteException ignored) {
                // ignored
            }
        }
        return false;
    }

    static float getDensityScale(Context context, ResourceManager res, int id)
            throws NotExistException, WrongTypeException, IOException {
        final int resourceDensity = res.getElement(id).getInteger();
        final int density;
        if (resourceDensity == DENSITY_DEFAULT) {
            density = DisplayAttributes.MEDIUM_DENSITY;
        } else if (resourceDensity != DENSITY_NONE) {
            density = resourceDensity;
        } else {
            density = 0;
        }
        final int targetDensity = DisplayManager.getInstance().getDefaultDisplay(context).get()
                .getRealAttributes().densityDpi;

        if (density > 0 && targetDensity > 0) {
            return (float) targetDensity / density;
        }
        return 1f;
    }

    static class GifViewAttributes {
        boolean freezesAnimation;
        int mLoopCount;

        GifViewAttributes(final Component view, final AttrSet attrs, final int defStyleAttr, final int defStyleRes) {
        }

        GifViewAttributes() {
            freezesAnimation = false;
            mLoopCount = -1;
        }
    }

    static class GifImageViewAttributes extends GifViewAttributes {
        final int mSourceResId;
        final int mBackgroundResId;

        GifImageViewAttributes(final Image view, final AttrSet attrs, final int defStyleAttr, final int defStyleRes)
                throws NotExistException, WrongTypeException, IOException {
            super(view, attrs, defStyleAttr, defStyleRes);
            mSourceResId = getResourceId(view, attrs, true);
            mBackgroundResId = getResourceId(view, attrs, false);
        }

        GifImageViewAttributes() {
            super();
            mSourceResId = 0;
            mBackgroundResId = 0;
        }

        private static int getResourceId(Image view, AttrSet attrs, final boolean isSrc)
                throws NotExistException, WrongTypeException, IOException {
            final int resId = attrs.getAttr("background").get().getIntegerValue();
            if (resId > 0) {
                return resId;
            }
            return 0;
        }

    }

    /**
     * gets Element for a given resid
     * @param context context
     * @param resid resource id
     * @return element
     * @throws IOException exception
     * @throws NotExistException exception
     */
    public static Element getElement(Context context, int resid) throws IOException, NotExistException {
        ResourceManager rm = context.getResourceManager();

        InputStream inputStream = null;
        Resource resource = rm.getResource(resid);
        if (resource instanceof InputStream) {
            inputStream = (InputStream) resource;
        }

        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
        resetOptions(decodingOpts);
        PixelMap pixelMap = decodePixelMap(inputStream, decodingOpts, "image/png");

        return new PixelMapElement(pixelMap);
    }

    private static void resetOptions(ImageSource.DecodingOptions decodingOpts) {
        decodingOpts.desiredSize = new Size(0, 0);
        decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
        decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
        decodingOpts.allowPartialImage = false;
        decodingOpts.desiredColorSpace = ColorSpace.UNKNOWN;
        decodingOpts.rotateDegrees = 0.0F;
        decodingOpts.sampleSize = 1;
    }

    /**
     * Decode the pixelmap
     * @param is inputstream
     * @param options decode options
     * @param formatHint format hint
     * @return pixelmap
     * @throws IOException exception
     */
    public static PixelMap decodePixelMap(InputStream is, ImageSource.DecodingOptions options, String formatHint)
            throws IOException {
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
        srcOpts.formatHint = formatHint;
        ImageSource imageSource = ImageSource.create(is, srcOpts);
        if (imageSource == null) {
            throw new FileNotFoundException();
        }
        return imageSource.createPixelmap(options);
    }
}
